home *** CD-ROM | disk | FTP | other *** search
/ Chip 2007 January, February, March & April / Chip-Cover-CD-2007-02.iso / Pakiet bezpieczenstwa / mini Pentoo LiveCD 2006.1 / mpentoo-2006.1.iso / livecd.squashfs / usr / lib / perl5 / 5.8.7 / Math / BigInt / Calc.pm next >
Text File  |  2006-04-25  |  60KB  |  2,103 lines

  1. package Math::BigInt::Calc;
  2.  
  3. use 5.005;
  4. use strict;
  5. # use warnings;    # dont use warnings for older Perls
  6.  
  7. use vars qw/$VERSION/;
  8.  
  9. $VERSION = '0.47';
  10.  
  11. # Package to store unsigned big integers in decimal and do math with them
  12.  
  13. # Internally the numbers are stored in an array with at least 1 element, no
  14. # leading zero parts (except the first) and in base 1eX where X is determined
  15. # automatically at loading time to be the maximum possible value
  16.  
  17. # todo:
  18. # - fully remove funky $# stuff in div() (maybe - that code scares me...)
  19.  
  20. # USE_MUL: due to problems on certain os (os390, posix-bc) "* 1e-5" is used
  21. # instead of "/ 1e5" at some places, (marked with USE_MUL). Other platforms
  22. # BS2000, some Crays need USE_DIV instead.
  23. # The BEGIN block is used to determine which of the two variants gives the
  24. # correct result.
  25.  
  26. # Beware of things like:
  27. # $i = $i * $y + $car; $car = int($i / $MBASE); $i = $i % $MBASE;
  28. # This works on x86, but fails on ARM (SA1100, iPAQ) due to whoknows what
  29. # reasons. So, use this instead (slower, but correct):
  30. # $i = $i * $y + $car; $car = int($i / $MBASE); $i -= $MBASE * $car;
  31.  
  32. ##############################################################################
  33. # global constants, flags and accessory
  34.  
  35. # announce that we are compatible with MBI v1.70 and up
  36. sub api_version () { 1; }
  37.  
  38. # constants for easier life
  39. my ($BASE,$BASE_LEN,$MBASE,$RBASE,$MAX_VAL,$BASE_LEN_SMALL);
  40. my ($AND_BITS,$XOR_BITS,$OR_BITS);
  41. my ($AND_MASK,$XOR_MASK,$OR_MASK);
  42.  
  43. sub _base_len 
  44.   {
  45.   # set/get the BASE_LEN and assorted other, connected values
  46.   # used only be the testsuite, set is used only by the BEGIN block below
  47.   shift;
  48.  
  49.   my $b = shift;
  50.   if (defined $b)
  51.     {
  52.     # find whether we can use mul or div or none in mul()/div()
  53.     # (in last case reduce BASE_LEN_SMALL)
  54.     $BASE_LEN_SMALL = $b+1;
  55.     my $caught = 0;
  56.     while (--$BASE_LEN_SMALL > 5)
  57.       {
  58.       $MBASE = int("1e".$BASE_LEN_SMALL);
  59.       $RBASE = abs('1e-'.$BASE_LEN_SMALL);        # see USE_MUL
  60.       $caught = 0;
  61.       $caught += 1 if (int($MBASE * $RBASE) != 1);    # should be 1
  62.       $caught += 2 if (int($MBASE / $MBASE) != 1);    # should be 1
  63.       last if $caught != 3;
  64.       }
  65.     # BASE_LEN is used for anything else than mul()/div()
  66.     $BASE_LEN = $BASE_LEN_SMALL;
  67.     $BASE_LEN = shift if (defined $_[0]);        # one more arg?
  68.     $BASE = int("1e".$BASE_LEN);
  69.  
  70.     $MBASE = int("1e".$BASE_LEN_SMALL);
  71.     $RBASE = abs('1e-'.$BASE_LEN_SMALL);        # see USE_MUL
  72.     $MAX_VAL = $MBASE-1;
  73.    
  74.     # avoid redefinitions
  75.  
  76.     undef &_mul;
  77.     undef &_div;
  78.  
  79.     # $caught & 1 != 0 => cannot use MUL
  80.     # $caught & 2 != 0 => cannot use DIV
  81.     # The parens around ($caught & 1) were important, indeed, if we would use
  82.     # & here.
  83.     if ($caught == 2)                # 2
  84.       {
  85.       # must USE_MUL since we cannot use DIV
  86.       *{_mul} = \&_mul_use_mul;
  87.       *{_div} = \&_div_use_mul;
  88.       }
  89.     else                    # 0 or 1
  90.       {
  91.       # can USE_DIV instead
  92.       *{_mul} = \&_mul_use_div;
  93.       *{_div} = \&_div_use_div;
  94.       }
  95.     }
  96.   return $BASE_LEN unless wantarray;
  97.   return ($BASE_LEN, $AND_BITS, $XOR_BITS, $OR_BITS, $BASE_LEN_SMALL, $MAX_VAL, $BASE);
  98.   }
  99.  
  100. sub _new
  101.   {
  102.   # (ref to string) return ref to num_array
  103.   # Convert a number from string format (without sign) to internal base
  104.   # 1ex format. Assumes normalized value as input.
  105.   my $il = length($_[1])-1;
  106.  
  107.   # < BASE_LEN due len-1 above
  108.   return [ int($_[1]) ] if $il < $BASE_LEN;    # shortcut for short numbers
  109.  
  110.   # this leaves '00000' instead of int 0 and will be corrected after any op
  111.   [ reverse(unpack("a" . ($il % $BASE_LEN+1) 
  112.     . ("a$BASE_LEN" x ($il / $BASE_LEN)), $_[1])) ];
  113.   }                                                                             
  114.  
  115. BEGIN
  116.   {
  117.   # from Daniel Pfeiffer: determine largest group of digits that is precisely
  118.   # multipliable with itself plus carry
  119.   # Test now changed to expect the proper pattern, not a result off by 1 or 2
  120.   my ($e, $num) = 3;    # lowest value we will use is 3+1-1 = 3
  121.   do 
  122.     {
  123.     $num = ('9' x ++$e) + 0;
  124.     $num *= $num + 1.0;
  125.     } while ("$num" =~ /9{$e}0{$e}/);    # must be a certain pattern
  126.   $e--;                 # last test failed, so retract one step
  127.   # the limits below brush the problems with the test above under the rug:
  128.   # the test should be able to find the proper $e automatically
  129.   $e = 5 if $^O =~ /^uts/;    # UTS get's some special treatment
  130.   $e = 5 if $^O =~ /^unicos/;    # unicos is also problematic (6 seems to work
  131.                 # there, but we play safe)
  132.   $e = 5 if $] < 5.006;        # cap, for older Perls
  133.   $e = 7 if $e > 7;        # cap, for VMS, OS/390 and other 64 bit systems
  134.                 # 8 fails inside random testsuite, so take 7
  135.  
  136.   __PACKAGE__->_base_len($e);    # set and store
  137.  
  138.   use integer;
  139.   # find out how many bits _and, _or and _xor can take (old default = 16)
  140.   # I don't think anybody has yet 128 bit scalars, so let's play safe.
  141.   local $^W = 0;    # don't warn about 'nonportable number'
  142.   $AND_BITS = 15; $XOR_BITS = 15; $OR_BITS = 15;
  143.  
  144.   # find max bits, we will not go higher than numberofbits that fit into $BASE
  145.   # to make _and etc simpler (and faster for smaller, slower for large numbers)
  146.   my $max = 16;
  147.   while (2 ** $max < $BASE) { $max++; }
  148.   {
  149.     no integer;
  150.     $max = 16 if $] < 5.006;    # older Perls might not take >16 too well
  151.   }
  152.   my ($x,$y,$z);
  153.   do {
  154.     $AND_BITS++;
  155.     $x = oct('0b' . '1' x $AND_BITS); $y = $x & $x;
  156.     $z = (2 ** $AND_BITS) - 1;
  157.     } while ($AND_BITS < $max && $x == $z && $y == $x);
  158.   $AND_BITS --;                        # retreat one step
  159.   do {
  160.     $XOR_BITS++;
  161.     $x = oct('0b' . '1' x $XOR_BITS); $y = $x ^ 0;
  162.     $z = (2 ** $XOR_BITS) - 1;
  163.     } while ($XOR_BITS < $max && $x == $z && $y == $x);
  164.   $XOR_BITS --;                        # retreat one step
  165.   do {
  166.     $OR_BITS++;
  167.     $x = oct('0b' . '1' x $OR_BITS); $y = $x | $x;
  168.     $z = (2 ** $OR_BITS) - 1;
  169.     } while ($OR_BITS < $max && $x == $z && $y == $x);
  170.   $OR_BITS --;                        # retreat one step
  171.   
  172.   $AND_MASK = __PACKAGE__->_new( ( 2 ** $AND_BITS ));
  173.   $XOR_MASK = __PACKAGE__->_new( ( 2 ** $XOR_BITS ));
  174.   $OR_MASK = __PACKAGE__->_new( ( 2 ** $OR_BITS ));
  175.   }
  176.  
  177. ###############################################################################
  178.  
  179. sub _zero
  180.   {
  181.   # create a zero
  182.   [ 0 ];
  183.   }
  184.  
  185. sub _one
  186.   {
  187.   # create a one
  188.   [ 1 ];
  189.   }
  190.  
  191. sub _two
  192.   {
  193.   # create a two (used internally for shifting)
  194.   [ 2 ];
  195.   }
  196.  
  197. sub _ten
  198.   {
  199.   # create a 10 (used internally for shifting)
  200.   [ 10 ];
  201.   }
  202.  
  203. sub _copy
  204.   {
  205.   # make a true copy
  206.   [ @{$_[1]} ];
  207.   }
  208.  
  209. # catch and throw away
  210. sub import { }
  211.  
  212. ##############################################################################
  213. # convert back to string and number
  214.  
  215. sub _str
  216.   {
  217.   # (ref to BINT) return num_str
  218.   # Convert number from internal base 100000 format to string format.
  219.   # internal format is always normalized (no leading zeros, "-0" => "+0")
  220.   my $ar = $_[1];
  221.  
  222.   my $l = scalar @$ar;                # number of parts
  223.   if ($l < 1)                    # should not happen
  224.     {
  225.     require Carp;
  226.     Carp::croak("$_[1] has no elements");
  227.     }
  228.  
  229.   my $ret = "";
  230.   # handle first one different to strip leading zeros from it (there are no
  231.   # leading zero parts in internal representation)
  232.   $l --; $ret .= int($ar->[$l]); $l--;
  233.   # Interestingly, the pre-padd method uses more time
  234.   # the old grep variant takes longer (14 vs. 10 sec)
  235.   my $z = '0' x ($BASE_LEN-1);                            
  236.   while ($l >= 0)
  237.     {
  238.     $ret .= substr($z.$ar->[$l],-$BASE_LEN); # fastest way I could think of
  239.     $l--;
  240.     }
  241.   $ret;
  242.   }                                                                             
  243.  
  244. sub _num
  245.   {
  246.   # Make a number (scalar int/float) from a BigInt object 
  247.   my $x = $_[1];
  248.  
  249.   return 0+$x->[0] if scalar @$x == 1;  # below $BASE
  250.   my $fac = 1;
  251.   my $num = 0;
  252.   foreach (@$x)
  253.     {
  254.     $num += $fac*$_; $fac *= $BASE;
  255.     }
  256.   $num; 
  257.   }
  258.  
  259. ##############################################################################
  260. # actual math code
  261.  
  262. sub _add
  263.   {
  264.   # (ref to int_num_array, ref to int_num_array)
  265.   # routine to add two base 1eX numbers
  266.   # stolen from Knuth Vol 2 Algorithm A pg 231
  267.   # there are separate routines to add and sub as per Knuth pg 233
  268.   # This routine clobbers up array x, but not y.
  269.  
  270.   my ($c,$x,$y) = @_;
  271.  
  272.   return $x if (@$y == 1) && $y->[0] == 0;        # $x + 0 => $x
  273.   if ((@$x == 1) && $x->[0] == 0)            # 0 + $y => $y->copy
  274.     {
  275.     # twice as slow as $x = [ @$y ], but necc. to retain $x as ref :(
  276.     @$x = @$y; return $x;        
  277.     }
  278.  
  279.   # for each in Y, add Y to X and carry. If after that, something is left in
  280.   # X, foreach in X add carry to X and then return X, carry
  281.   # Trades one "$j++" for having to shift arrays
  282.   my $i; my $car = 0; my $j = 0;
  283.   for $i (@$y)
  284.     {
  285.     $x->[$j] -= $BASE if $car = (($x->[$j] += $i + $car) >= $BASE) ? 1 : 0;
  286.     $j++;
  287.     }
  288.   while ($car != 0)
  289.     {
  290.     $x->[$j] -= $BASE if $car = (($x->[$j] += $car) >= $BASE) ? 1 : 0; $j++;
  291.     }
  292.   $x;
  293.   }                                                                             
  294.  
  295. sub _inc
  296.   {
  297.   # (ref to int_num_array, ref to int_num_array)
  298.   # Add 1 to $x, modify $x in place
  299.   my ($c,$x) = @_;
  300.  
  301.   for my $i (@$x)
  302.     {
  303.     return $x if (($i += 1) < $BASE);        # early out
  304.     $i = 0;                    # overflow, next
  305.     }
  306.   push @$x,1 if (($x->[-1] || 0) == 0);        # last overflowed, so extend
  307.   $x;
  308.   }                                                                             
  309.  
  310. sub _dec
  311.   {
  312.   # (ref to int_num_array, ref to int_num_array)
  313.   # Sub 1 from $x, modify $x in place
  314.   my ($c,$x) = @_;
  315.  
  316.   my $MAX = $BASE-1;                # since MAX_VAL based on MBASE
  317.   for my $i (@$x)
  318.     {
  319.     last if (($i -= 1) >= 0);            # early out
  320.     $i = $MAX;                    # underflow, next
  321.     }
  322.   pop @$x if $x->[-1] == 0 && @$x > 1;        # last underflowed (but leave 0)
  323.   $x;
  324.   }                                                                             
  325.  
  326. sub _sub
  327.   {
  328.   # (ref to int_num_array, ref to int_num_array, swap)
  329.   # subtract base 1eX numbers -- stolen from Knuth Vol 2 pg 232, $x > $y
  330.   # subtract Y from X by modifying x in place
  331.   my ($c,$sx,$sy,$s) = @_;
  332.  
  333.   my $car = 0; my $i; my $j = 0;
  334.   if (!$s)
  335.     {
  336.     for $i (@$sx)
  337.       {
  338.       last unless defined $sy->[$j] || $car;
  339.       $i += $BASE if $car = (($i -= ($sy->[$j] || 0) + $car) < 0); $j++;
  340.       }
  341.     # might leave leading zeros, so fix that
  342.     return __strip_zeros($sx);
  343.     }
  344.   for $i (@$sx)
  345.     {
  346.     # we can't do an early out if $x is < than $y, since we
  347.     # need to copy the high chunks from $y. Found by Bob Mathews.
  348.     #last unless defined $sy->[$j] || $car;
  349.     $sy->[$j] += $BASE
  350.      if $car = (($sy->[$j] = $i-($sy->[$j]||0) - $car) < 0);
  351.     $j++;
  352.     }
  353.   # might leave leading zeros, so fix that
  354.   __strip_zeros($sy);
  355.   }                                                                             
  356.  
  357. sub _mul_use_mul
  358.   {
  359.   # (ref to int_num_array, ref to int_num_array)
  360.   # multiply two numbers in internal representation
  361.   # modifies first arg, second need not be different from first
  362.   my ($c,$xv,$yv) = @_;
  363.  
  364.   if (@$yv == 1)
  365.     {
  366.     # shortcut for two very short numbers (improved by Nathan Zook)
  367.     # works also if xv and yv are the same reference, and handles also $x == 0
  368.     if (@$xv == 1)
  369.       {
  370.       if (($xv->[0] *= $yv->[0]) >= $MBASE)
  371.          {
  372.          $xv->[0] = $xv->[0] - ($xv->[1] = int($xv->[0] * $RBASE)) * $MBASE;
  373.          };
  374.       return $xv;
  375.       }
  376.     # $x * 0 => 0
  377.     if ($yv->[0] == 0)
  378.       {
  379.       @$xv = (0);
  380.       return $xv;
  381.       }
  382.     # multiply a large number a by a single element one, so speed up
  383.     my $y = $yv->[0]; my $car = 0;
  384.     foreach my $i (@$xv)
  385.       {
  386.       $i = $i * $y + $car; $car = int($i * $RBASE); $i -= $car * $MBASE;
  387.       }
  388.     push @$xv, $car if $car != 0;
  389.     return $xv;
  390.     }
  391.   # shortcut for result $x == 0 => result = 0
  392.   return $xv if ( ((@$xv == 1) && ($xv->[0] == 0)) ); 
  393.  
  394.   # since multiplying $x with $x fails, make copy in this case
  395.   $yv = [@$xv] if $xv == $yv;    # same references?
  396.  
  397.   my @prod = (); my ($prod,$car,$cty,$xi,$yi);
  398.  
  399.   for $xi (@$xv)
  400.     {
  401.     $car = 0; $cty = 0;
  402.  
  403.     # slow variant
  404. #    for $yi (@$yv)
  405. #      {
  406. #      $prod = $xi * $yi + ($prod[$cty] || 0) + $car;
  407. #      $prod[$cty++] =
  408. #       $prod - ($car = int($prod * RBASE)) * $MBASE;  # see USE_MUL
  409. #      }
  410. #    $prod[$cty] += $car if $car; # need really to check for 0?
  411. #    $xi = shift @prod;
  412.  
  413.     # faster variant
  414.     # looping through this if $xi == 0 is silly - so optimize it away!
  415.     $xi = (shift @prod || 0), next if $xi == 0;
  416.     for $yi (@$yv)
  417.       {
  418.       $prod = $xi * $yi + ($prod[$cty] || 0) + $car;
  419. ##     this is actually a tad slower
  420. ##        $prod = $prod[$cty]; $prod += ($car + $xi * $yi);    # no ||0 here
  421.       $prod[$cty++] =
  422.        $prod - ($car = int($prod * $RBASE)) * $MBASE;  # see USE_MUL
  423.       }
  424.     $prod[$cty] += $car if $car; # need really to check for 0?
  425.     $xi = shift @prod || 0;    # || 0 makes v5.005_3 happy
  426.     }
  427.   push @$xv, @prod;
  428.   __strip_zeros($xv);
  429.   $xv;
  430.   }                                                                             
  431.  
  432. sub _mul_use_div
  433.   {
  434.   # (ref to int_num_array, ref to int_num_array)
  435.   # multiply two numbers in internal representation
  436.   # modifies first arg, second need not be different from first
  437.   my ($c,$xv,$yv) = @_;
  438.  
  439.   if (@$yv == 1)
  440.     {
  441.     # shortcut for two small numbers, also handles $x == 0
  442.     if (@$xv == 1)
  443.       {
  444.       # shortcut for two very short numbers (improved by Nathan Zook)
  445.       # works also if xv and yv are the same reference, and handles also $x == 0
  446.       if (($xv->[0] *= $yv->[0]) >= $MBASE)
  447.           {
  448.           $xv->[0] =
  449.               $xv->[0] - ($xv->[1] = int($xv->[0] / $MBASE)) * $MBASE;
  450.           };
  451.       return $xv;
  452.       }
  453.     # $x * 0 => 0
  454.     if ($yv->[0] == 0)
  455.       {
  456.       @$xv = (0);
  457.       return $xv;
  458.       }
  459.     # multiply a large number a by a single element one, so speed up
  460.     my $y = $yv->[0]; my $car = 0;
  461.     foreach my $i (@$xv)
  462.       {
  463.       $i = $i * $y + $car; $car = int($i / $MBASE); $i -= $car * $MBASE;
  464.       }
  465.     push @$xv, $car if $car != 0;
  466.     return $xv;
  467.     }
  468.   # shortcut for result $x == 0 => result = 0
  469.   return $xv if ( ((@$xv == 1) && ($xv->[0] == 0)) ); 
  470.  
  471.   # since multiplying $x with $x fails, make copy in this case
  472.   $yv = [@$xv] if $xv == $yv;    # same references?
  473.  
  474.   my @prod = (); my ($prod,$car,$cty,$xi,$yi);
  475.   for $xi (@$xv)
  476.     {
  477.     $car = 0; $cty = 0;
  478.     # looping through this if $xi == 0 is silly - so optimize it away!
  479.     $xi = (shift @prod || 0), next if $xi == 0;
  480.     for $yi (@$yv)
  481.       {
  482.       $prod = $xi * $yi + ($prod[$cty] || 0) + $car;
  483.       $prod[$cty++] =
  484.        $prod - ($car = int($prod / $MBASE)) * $MBASE;
  485.       }
  486.     $prod[$cty] += $car if $car; # need really to check for 0?
  487.     $xi = shift @prod || 0;    # || 0 makes v5.005_3 happy
  488.     }
  489.   push @$xv, @prod;
  490.   __strip_zeros($xv);
  491.   $xv;
  492.   }                                                                             
  493.  
  494. sub _div_use_mul
  495.   {
  496.   # ref to array, ref to array, modify first array and return remainder if 
  497.   # in list context
  498.  
  499.   # see comments in _div_use_div() for more explanations
  500.  
  501.   my ($c,$x,$yorg) = @_;
  502.   
  503.   # the general div algorithmn here is about O(N*N) and thus quite slow, so
  504.   # we first check for some special cases and use shortcuts to handle them.
  505.  
  506.   # This works, because we store the numbers in a chunked format where each
  507.   # element contains 5..7 digits (depending on system).
  508.  
  509.   # if both numbers have only one element:
  510.   if (@$x == 1 && @$yorg == 1)
  511.     {
  512.     # shortcut, $yorg and $x are two small numbers
  513.     if (wantarray)
  514.       {
  515.       my $r = [ $x->[0] % $yorg->[0] ];
  516.       $x->[0] = int($x->[0] / $yorg->[0]);
  517.       return ($x,$r); 
  518.       }
  519.     else
  520.       {
  521.       $x->[0] = int($x->[0] / $yorg->[0]);
  522.       return $x; 
  523.       }
  524.     }
  525.  
  526.   # if x has more than one, but y has only one element:
  527.   if (@$yorg == 1)
  528.     {
  529.     my $rem;
  530.     $rem = _mod($c,[ @$x ],$yorg) if wantarray;
  531.  
  532.     # shortcut, $y is < $BASE
  533.     my $j = scalar @$x; my $r = 0; 
  534.     my $y = $yorg->[0]; my $b;
  535.     while ($j-- > 0)
  536.       {
  537.       $b = $r * $MBASE + $x->[$j];
  538.       $x->[$j] = int($b/$y);
  539.       $r = $b % $y;
  540.       }
  541.     pop @$x if @$x > 1 && $x->[-1] == 0;    # splice up a leading zero 
  542.     return ($x,$rem) if wantarray;
  543.     return $x;
  544.     }
  545.  
  546.   # now x and y have more than one element
  547.  
  548.   # check whether y has more elements than x, if yet, the result will be 0
  549.   if (@$yorg > @$x)
  550.     {
  551.     my $rem;
  552.     $rem = [@$x] if wantarray;                  # make copy
  553.     splice (@$x,1);                             # keep ref to original array
  554.     $x->[0] = 0;                                # set to 0
  555.     return ($x,$rem) if wantarray;              # including remainder?
  556.     return $x;                    # only x, which is [0] now
  557.     }
  558.   # check whether the numbers have the same number of elements, in that case
  559.   # the result will fit into one element and can be computed efficiently
  560.   if (@$yorg == @$x)
  561.     {
  562.     my $rem;
  563.     # if $yorg has more digits than $x (it's leading element is longer than
  564.     # the one from $x), the result will also be 0:
  565.     if (length(int($yorg->[-1])) > length(int($x->[-1])))
  566.       {
  567.       $rem = [@$x] if wantarray;        # make copy
  568.       splice (@$x,1);                # keep ref to org array
  569.       $x->[0] = 0;                # set to 0
  570.       return ($x,$rem) if wantarray;        # including remainder?
  571.       return $x;
  572.       }
  573.     # now calculate $x / $yorg
  574.     if (length(int($yorg->[-1])) == length(int($x->[-1])))
  575.       {
  576.       # same length, so make full compare
  577.  
  578.       my $a = 0; my $j = scalar @$x - 1;
  579.       # manual way (abort if unequal, good for early ne)
  580.       while ($j >= 0)
  581.         {
  582.         last if ($a = $x->[$j] - $yorg->[$j]); $j--;
  583.         }
  584.       # $a contains the result of the compare between X and Y
  585.       # a < 0: x < y, a == 0: x == y, a > 0: x > y
  586.       if ($a <= 0)
  587.         {
  588.         $rem = [ 0 ];                   # a = 0 => x == y => rem 0
  589.         $rem = [@$x] if $a != 0;        # a < 0 => x < y => rem = x
  590.         splice(@$x,1);                  # keep single element
  591.         $x->[0] = 0;                    # if $a < 0
  592.         $x->[0] = 1 if $a == 0;         # $x == $y
  593.         return ($x,$rem) if wantarray;
  594.         return $x;
  595.         }
  596.       # $x >= $y, so proceed normally
  597.       }
  598.     }
  599.  
  600.   # all other cases:
  601.  
  602.   my $y = [ @$yorg ];                # always make copy to preserve
  603.  
  604.   my ($car,$bar,$prd,$dd,$xi,$yi,@q,$v2,$v1,@d,$tmp,$q,$u2,$u1,$u0);
  605.  
  606.   $car = $bar = $prd = 0;
  607.   if (($dd = int($MBASE/($y->[-1]+1))) != 1) 
  608.     {
  609.     for $xi (@$x) 
  610.       {
  611.       $xi = $xi * $dd + $car;
  612.       $xi -= ($car = int($xi * $RBASE)) * $MBASE;    # see USE_MUL
  613.       }
  614.     push(@$x, $car); $car = 0;
  615.     for $yi (@$y) 
  616.       {
  617.       $yi = $yi * $dd + $car;
  618.       $yi -= ($car = int($yi * $RBASE)) * $MBASE;    # see USE_MUL
  619.       }
  620.     }
  621.   else 
  622.     {
  623.     push(@$x, 0);
  624.     }
  625.   @q = (); ($v2,$v1) = @$y[-2,-1];
  626.   $v2 = 0 unless $v2;
  627.   while ($#$x > $#$y) 
  628.     {
  629.     ($u2,$u1,$u0) = @$x[-3..-1];
  630.     $u2 = 0 unless $u2;
  631.     #warn "oups v1 is 0, u0: $u0 $y->[-2] $y->[-1] l ",scalar @$y,"\n"
  632.     # if $v1 == 0;
  633.     $q = (($u0 == $v1) ? $MAX_VAL : int(($u0*$MBASE+$u1)/$v1));
  634.     --$q while ($v2*$q > ($u0*$MBASE+$u1-$q*$v1)*$MBASE+$u2);
  635.     if ($q)
  636.       {
  637.       ($car, $bar) = (0,0);
  638.       for ($yi = 0, $xi = $#$x-$#$y-1; $yi <= $#$y; ++$yi,++$xi) 
  639.         {
  640.         $prd = $q * $y->[$yi] + $car;
  641.         $prd -= ($car = int($prd * $RBASE)) * $MBASE;    # see USE_MUL
  642.     $x->[$xi] += $MBASE if ($bar = (($x->[$xi] -= $prd + $bar) < 0));
  643.     }
  644.       if ($x->[-1] < $car + $bar) 
  645.         {
  646.         $car = 0; --$q;
  647.     for ($yi = 0, $xi = $#$x-$#$y-1; $yi <= $#$y; ++$yi,++$xi) 
  648.           {
  649.       $x->[$xi] -= $MBASE
  650.        if ($car = (($x->[$xi] += $y->[$yi] + $car) >= $MBASE));
  651.       }
  652.     }   
  653.       }
  654.     pop(@$x);
  655.     unshift(@q, $q);
  656.     }
  657.   if (wantarray) 
  658.     {
  659.     @d = ();
  660.     if ($dd != 1)  
  661.       {
  662.       $car = 0; 
  663.       for $xi (reverse @$x) 
  664.         {
  665.         $prd = $car * $MBASE + $xi;
  666.         $car = $prd - ($tmp = int($prd / $dd)) * $dd; # see USE_MUL
  667.         unshift(@d, $tmp);
  668.         }
  669.       }
  670.     else 
  671.       {
  672.       @d = @$x;
  673.       }
  674.     @$x = @q;
  675.     my $d = \@d; 
  676.     __strip_zeros($x);
  677.     __strip_zeros($d);
  678.     return ($x,$d);
  679.     }
  680.   @$x = @q;
  681.   __strip_zeros($x);
  682.   $x;
  683.   }
  684.  
  685. sub _div_use_div
  686.   {
  687.   # ref to array, ref to array, modify first array and return remainder if 
  688.   # in list context
  689.   my ($c,$x,$yorg) = @_;
  690.  
  691.   # the general div algorithmn here is about O(N*N) and thus quite slow, so
  692.   # we first check for some special cases and use shortcuts to handle them.
  693.  
  694.   # This works, because we store the numbers in a chunked format where each
  695.   # element contains 5..7 digits (depending on system).
  696.  
  697.   # if both numbers have only one element:
  698.   if (@$x == 1 && @$yorg == 1)
  699.     {
  700.     # shortcut, $yorg and $x are two small numbers
  701.     if (wantarray)
  702.       {
  703.       my $r = [ $x->[0] % $yorg->[0] ];
  704.       $x->[0] = int($x->[0] / $yorg->[0]);
  705.       return ($x,$r); 
  706.       }
  707.     else
  708.       {
  709.       $x->[0] = int($x->[0] / $yorg->[0]);
  710.       return $x; 
  711.       }
  712.     }
  713.   # if x has more than one, but y has only one element:
  714.   if (@$yorg == 1)
  715.     {
  716.     my $rem;
  717.     $rem = _mod($c,[ @$x ],$yorg) if wantarray;
  718.  
  719.     # shortcut, $y is < $BASE
  720.     my $j = scalar @$x; my $r = 0; 
  721.     my $y = $yorg->[0]; my $b;
  722.     while ($j-- > 0)
  723.       {
  724.       $b = $r * $MBASE + $x->[$j];
  725.       $x->[$j] = int($b/$y);
  726.       $r = $b % $y;
  727.       }
  728.     pop @$x if @$x > 1 && $x->[-1] == 0;    # splice up a leading zero 
  729.     return ($x,$rem) if wantarray;
  730.     return $x;
  731.     }
  732.   # now x and y have more than one element
  733.  
  734.   # check whether y has more elements than x, if yet, the result will be 0
  735.   if (@$yorg > @$x)
  736.     {
  737.     my $rem;
  738.     $rem = [@$x] if wantarray;            # make copy
  739.     splice (@$x,1);                # keep ref to original array
  740.     $x->[0] = 0;                # set to 0
  741.     return ($x,$rem) if wantarray;        # including remainder?
  742.     return $x;                    # only x, which is [0] now
  743.     }
  744.   # check whether the numbers have the same number of elements, in that case
  745.   # the result will fit into one element and can be computed efficiently
  746.   if (@$yorg == @$x)
  747.     {
  748.     my $rem;
  749.     # if $yorg has more digits than $x (it's leading element is longer than
  750.     # the one from $x), the result will also be 0:
  751.     if (length(int($yorg->[-1])) > length(int($x->[-1])))
  752.       {
  753.       $rem = [@$x] if wantarray;        # make copy
  754.       splice (@$x,1);                # keep ref to org array
  755.       $x->[0] = 0;                # set to 0
  756.       return ($x,$rem) if wantarray;        # including remainder?
  757.       return $x;
  758.       }
  759.     # now calculate $x / $yorg
  760.  
  761.     if (length(int($yorg->[-1])) == length(int($x->[-1])))
  762.       {
  763.       # same length, so make full compare
  764.  
  765.       my $a = 0; my $j = scalar @$x - 1;
  766.       # manual way (abort if unequal, good for early ne)
  767.       while ($j >= 0)
  768.         {
  769.         last if ($a = $x->[$j] - $yorg->[$j]); $j--;
  770.         }
  771.       # $a contains the result of the compare between X and Y
  772.       # a < 0: x < y, a == 0: x == y, a > 0: x > y
  773.       if ($a <= 0)
  774.         {
  775.         $rem = [ 0 ];            # a = 0 => x == y => rem 0
  776.         $rem = [@$x] if $a != 0;    # a < 0 => x < y => rem = x
  777.         splice(@$x,1);            # keep single element
  778.         $x->[0] = 0;            # if $a < 0
  779.         $x->[0] = 1 if $a == 0;     # $x == $y
  780.         return ($x,$rem) if wantarray;    # including remainder?
  781.         return $x;
  782.         }
  783.       # $x >= $y, so proceed normally
  784.  
  785.       }
  786.     }
  787.  
  788.   # all other cases:
  789.  
  790.   my $y = [ @$yorg ];                # always make copy to preserve
  791.  
  792.   my ($car,$bar,$prd,$dd,$xi,$yi,@q,$v2,$v1,@d,$tmp,$q,$u2,$u1,$u0);
  793.  
  794.   $car = $bar = $prd = 0;
  795.   if (($dd = int($MBASE/($y->[-1]+1))) != 1) 
  796.     {
  797.     for $xi (@$x) 
  798.       {
  799.       $xi = $xi * $dd + $car;
  800.       $xi -= ($car = int($xi / $MBASE)) * $MBASE;
  801.       }
  802.     push(@$x, $car); $car = 0;
  803.     for $yi (@$y) 
  804.       {
  805.       $yi = $yi * $dd + $car;
  806.       $yi -= ($car = int($yi / $MBASE)) * $MBASE;
  807.       }
  808.     }
  809.   else 
  810.     {
  811.     push(@$x, 0);
  812.     }
  813.  
  814.   # @q will accumulate the final result, $q contains the current computed
  815.   # part of the final result
  816.  
  817.   @q = (); ($v2,$v1) = @$y[-2,-1];
  818.   $v2 = 0 unless $v2;
  819.   while ($#$x > $#$y) 
  820.     {
  821.     ($u2,$u1,$u0) = @$x[-3..-1];
  822.     $u2 = 0 unless $u2;
  823.     #warn "oups v1 is 0, u0: $u0 $y->[-2] $y->[-1] l ",scalar @$y,"\n"
  824.     # if $v1 == 0;
  825.     $q = (($u0 == $v1) ? $MAX_VAL : int(($u0*$MBASE+$u1)/$v1));
  826.     --$q while ($v2*$q > ($u0*$MBASE+$u1-$q*$v1)*$MBASE+$u2);
  827.     if ($q)
  828.       {
  829.       ($car, $bar) = (0,0);
  830.       for ($yi = 0, $xi = $#$x-$#$y-1; $yi <= $#$y; ++$yi,++$xi) 
  831.         {
  832.         $prd = $q * $y->[$yi] + $car;
  833.         $prd -= ($car = int($prd / $MBASE)) * $MBASE;
  834.     $x->[$xi] += $MBASE if ($bar = (($x->[$xi] -= $prd + $bar) < 0));
  835.     }
  836.       if ($x->[-1] < $car + $bar) 
  837.         {
  838.         $car = 0; --$q;
  839.     for ($yi = 0, $xi = $#$x-$#$y-1; $yi <= $#$y; ++$yi,++$xi) 
  840.           {
  841.       $x->[$xi] -= $MBASE
  842.        if ($car = (($x->[$xi] += $y->[$yi] + $car) >= $MBASE));
  843.       }
  844.     }   
  845.       }
  846.     pop(@$x); unshift(@q, $q);
  847.     }
  848.   if (wantarray) 
  849.     {
  850.     @d = ();
  851.     if ($dd != 1)  
  852.       {
  853.       $car = 0; 
  854.       for $xi (reverse @$x) 
  855.         {
  856.         $prd = $car * $MBASE + $xi;
  857.         $car = $prd - ($tmp = int($prd / $dd)) * $dd;
  858.         unshift(@d, $tmp);
  859.         }
  860.       }
  861.     else 
  862.       {
  863.       @d = @$x;
  864.       }
  865.     @$x = @q;
  866.     my $d = \@d; 
  867.     __strip_zeros($x);
  868.     __strip_zeros($d);
  869.     return ($x,$d);
  870.     }
  871.   @$x = @q;
  872.   __strip_zeros($x);
  873.   $x;
  874.   }
  875.  
  876. ##############################################################################
  877. # testing
  878.  
  879. sub _acmp
  880.   {
  881.   # internal absolute post-normalized compare (ignore signs)
  882.   # ref to array, ref to array, return <0, 0, >0
  883.   # arrays must have at least one entry; this is not checked for
  884.   my ($c,$cx,$cy) = @_;
  885.  
  886.   # shortcut for short numbers 
  887.   return (($cx->[0] <=> $cy->[0]) <=> 0) 
  888.    if scalar @$cx == scalar @$cy && scalar @$cx == 1;
  889.  
  890.   # fast comp based on number of array elements (aka pseudo-length)
  891.   my $lxy = (scalar @$cx - scalar @$cy)
  892.   # or length of first element if same number of elements (aka difference 0)
  893.     ||
  894.   # need int() here because sometimes the last element is '00018' vs '18'
  895.    (length(int($cx->[-1])) - length(int($cy->[-1])));
  896.   return -1 if $lxy < 0;                # already differs, ret
  897.   return 1 if $lxy > 0;                    # ditto
  898.  
  899.   # manual way (abort if unequal, good for early ne)
  900.   my $a; my $j = scalar @$cx;
  901.   while (--$j >= 0)
  902.     {
  903.     last if ($a = $cx->[$j] - $cy->[$j]);
  904.     }
  905.   $a <=> 0;
  906.   }
  907.  
  908. sub _len
  909.   {
  910.   # compute number of digits
  911.  
  912.   # int() because add/sub sometimes leaves strings (like '00005') instead of
  913.   # '5' in this place, thus causing length() to report wrong length
  914.   my $cx = $_[1];
  915.  
  916.   (@$cx-1)*$BASE_LEN+length(int($cx->[-1]));
  917.   }
  918.  
  919. sub _digit
  920.   {
  921.   # return the nth digit, negative values count backward
  922.   # zero is rightmost, so _digit(123,0) will give 3
  923.   my ($c,$x,$n) = @_;
  924.  
  925.   my $len = _len('',$x);
  926.  
  927.   $n = $len+$n if $n < 0;        # -1 last, -2 second-to-last
  928.   $n = abs($n);                # if negative was too big
  929.   $len--; $n = $len if $n > $len;    # n to big?
  930.   
  931.   my $elem = int($n / $BASE_LEN);    # which array element
  932.   my $digit = $n % $BASE_LEN;        # which digit in this element
  933.   $elem = '0' x $BASE_LEN . @$x[$elem];    # get element padded with 0's
  934.   substr($elem,-$digit-1,1);
  935.   }
  936.  
  937. sub _zeros
  938.   {
  939.   # return amount of trailing zeros in decimal
  940.   # check each array elem in _m for having 0 at end as long as elem == 0
  941.   # Upon finding a elem != 0, stop
  942.   my $x = $_[1];
  943.  
  944.   return 0 if scalar @$x == 1 && $x->[0] == 0;
  945.  
  946.   my $zeros = 0; my $elem;
  947.   foreach my $e (@$x)
  948.     {
  949.     if ($e != 0)
  950.       {
  951.       $elem = "$e";                # preserve x
  952.       $elem =~ s/.*?(0*$)/$1/;            # strip anything not zero
  953.       $zeros *= $BASE_LEN;            # elems * 5
  954.       $zeros += length($elem);            # count trailing zeros
  955.       last;                    # early out
  956.       }
  957.     $zeros ++;                    # real else branch: 50% slower!
  958.     }
  959.   $zeros;
  960.   }
  961.  
  962. ##############################################################################
  963. # _is_* routines
  964.  
  965. sub _is_zero
  966.   {
  967.   # return true if arg is zero 
  968.   (((scalar @{$_[1]} == 1) && ($_[1]->[0] == 0))) <=> 0;
  969.   }
  970.  
  971. sub _is_even
  972.   {
  973.   # return true if arg is even
  974.   (!($_[1]->[0] & 1)) <=> 0; 
  975.   }
  976.  
  977. sub _is_odd
  978.   {
  979.   # return true if arg is even
  980.   (($_[1]->[0] & 1)) <=> 0; 
  981.   }
  982.  
  983. sub _is_one
  984.   {
  985.   # return true if arg is one
  986.   (scalar @{$_[1]} == 1) && ($_[1]->[0] == 1) <=> 0; 
  987.   }
  988.  
  989. sub _is_two
  990.   {
  991.   # return true if arg is two 
  992.   (scalar @{$_[1]} == 1) && ($_[1]->[0] == 2) <=> 0; 
  993.   }
  994.  
  995. sub _is_ten
  996.   {
  997.   # return true if arg is ten 
  998.   (scalar @{$_[1]} == 1) && ($_[1]->[0] == 10) <=> 0; 
  999.   }
  1000.  
  1001. sub __strip_zeros
  1002.   {
  1003.   # internal normalization function that strips leading zeros from the array
  1004.   # args: ref to array
  1005.   my $s = shift;
  1006.  
  1007.   my $cnt = scalar @$s; # get count of parts
  1008.   my $i = $cnt-1;
  1009.   push @$s,0 if $i < 0;        # div might return empty results, so fix it
  1010.  
  1011.   return $s if @$s == 1;        # early out
  1012.  
  1013.   #print "strip: cnt $cnt i $i\n";
  1014.   # '0', '3', '4', '0', '0',
  1015.   #  0    1    2    3    4
  1016.   # cnt = 5, i = 4
  1017.   # i = 4
  1018.   # i = 3
  1019.   # => fcnt = cnt - i (5-2 => 3, cnt => 5-1 = 4, throw away from 4th pos)
  1020.   # >= 1: skip first part (this can be zero)
  1021.   while ($i > 0) { last if $s->[$i] != 0; $i--; }
  1022.   $i++; splice @$s,$i if ($i < $cnt); # $i cant be 0
  1023.   $s;                                                                    
  1024.   }                                                                             
  1025.  
  1026. ###############################################################################
  1027. # check routine to test internal state for corruptions
  1028.  
  1029. sub _check
  1030.   {
  1031.   # used by the test suite
  1032.   my $x = $_[1];
  1033.  
  1034.   return "$x is not a reference" if !ref($x);
  1035.  
  1036.   # are all parts are valid?
  1037.   my $i = 0; my $j = scalar @$x; my ($e,$try);
  1038.   while ($i < $j)
  1039.     {
  1040.     $e = $x->[$i]; $e = 'undef' unless defined $e;
  1041.     $try = '=~ /^[\+]?[0-9]+\$/; '."($x, $e)";
  1042.     last if $e !~ /^[+]?[0-9]+$/;
  1043.     $try = '=~ /^[\+]?[0-9]+\$/; '."($x, $e) (stringify)";
  1044.     last if "$e" !~ /^[+]?[0-9]+$/;
  1045.     $try = '=~ /^[\+]?[0-9]+\$/; '."($x, $e) (cat-stringify)";
  1046.     last if '' . "$e" !~ /^[+]?[0-9]+$/;
  1047.     $try = ' < 0 || >= $BASE; '."($x, $e)";
  1048.     last if $e <0 || $e >= $BASE;
  1049.     # this test is disabled, since new/bnorm and certain ops (like early out
  1050.     # in add/sub) are allowed/expected to leave '00000' in some elements
  1051.     #$try = '=~ /^00+/; '."($x, $e)";
  1052.     #last if $e =~ /^00+/;
  1053.     $i++;
  1054.     }
  1055.   return "Illegal part '$e' at pos $i (tested: $try)" if $i < $j;
  1056.   0;
  1057.   }
  1058.  
  1059.  
  1060. ###############################################################################
  1061.  
  1062. sub _mod
  1063.   {
  1064.   # if possible, use mod shortcut
  1065.   my ($c,$x,$yo) = @_;
  1066.  
  1067.   # slow way since $y to big
  1068.   if (scalar @$yo > 1)
  1069.     {
  1070.     my ($xo,$rem) = _div($c,$x,$yo);
  1071.     return $rem;
  1072.     }
  1073.  
  1074.   my $y = $yo->[0];
  1075.   # both are single element arrays
  1076.   if (scalar @$x == 1)
  1077.     {
  1078.     $x->[0] %= $y;
  1079.     return $x;
  1080.     }
  1081.  
  1082.   # @y is a single element, but @x has more than one element
  1083.   my $b = $BASE % $y;
  1084.   if ($b == 0)
  1085.     {
  1086.     # when BASE % Y == 0 then (B * BASE) % Y == 0
  1087.     # (B * BASE) % $y + A % Y => A % Y
  1088.     # so need to consider only last element: O(1)
  1089.     $x->[0] %= $y;
  1090.     }
  1091.   elsif ($b == 1)
  1092.     {
  1093.     # else need to go through all elements: O(N), but loop is a bit simplified
  1094.     my $r = 0;
  1095.     foreach (@$x)
  1096.       {
  1097.       $r = ($r + $_) % $y;        # not much faster, but heh...
  1098.       #$r += $_ % $y; $r %= $y;
  1099.       }
  1100.     $r = 0 if $r == $y;
  1101.     $x->[0] = $r;
  1102.     }
  1103.   else
  1104.     {
  1105.     # else need to go through all elements: O(N)
  1106.     my $r = 0; my $bm = 1;
  1107.     foreach (@$x)
  1108.       {
  1109.       $r = ($_ * $bm + $r) % $y;
  1110.       $bm = ($bm * $b) % $y;
  1111.  
  1112.       #$r += ($_ % $y) * $bm;
  1113.       #$bm *= $b;
  1114.       #$bm %= $y;
  1115.       #$r %= $y;
  1116.       }
  1117.     $r = 0 if $r == $y;
  1118.     $x->[0] = $r;
  1119.     }
  1120.   splice (@$x,1);        # keep one element of $x
  1121.   $x;
  1122.   }
  1123.  
  1124. ##############################################################################
  1125. # shifts
  1126.  
  1127. sub _rsft
  1128.   {
  1129.   my ($c,$x,$y,$n) = @_;
  1130.  
  1131.   if ($n != 10)
  1132.     {
  1133.     $n = _new($c,$n); return _div($c,$x, _pow($c,$n,$y));
  1134.     }
  1135.  
  1136.   # shortcut (faster) for shifting by 10)
  1137.   # multiples of $BASE_LEN
  1138.   my $dst = 0;                # destination
  1139.   my $src = _num($c,$y);        # as normal int
  1140.   my $xlen = (@$x-1)*$BASE_LEN+length(int($x->[-1]));  # len of x in digits
  1141.   if ($src >= $xlen or ($src == $xlen and ! defined $x->[1]))
  1142.     {
  1143.     # 12345 67890 shifted right by more than 10 digits => 0
  1144.     splice (@$x,1);                    # leave only one element
  1145.     $x->[0] = 0;                       # set to zero
  1146.     return $x;
  1147.     }
  1148.   my $rem = $src % $BASE_LEN;        # remainder to shift
  1149.   $src = int($src / $BASE_LEN);        # source
  1150.   if ($rem == 0)
  1151.     {
  1152.     splice (@$x,0,$src);        # even faster, 38.4 => 39.3
  1153.     }
  1154.   else
  1155.     {
  1156.     my $len = scalar @$x - $src;    # elems to go
  1157.     my $vd; my $z = '0'x $BASE_LEN;
  1158.     $x->[scalar @$x] = 0;        # avoid || 0 test inside loop
  1159.     while ($dst < $len)
  1160.       {
  1161.       $vd = $z.$x->[$src];
  1162.       $vd = substr($vd,-$BASE_LEN,$BASE_LEN-$rem);
  1163.       $src++;
  1164.       $vd = substr($z.$x->[$src],-$rem,$rem) . $vd;
  1165.       $vd = substr($vd,-$BASE_LEN,$BASE_LEN) if length($vd) > $BASE_LEN;
  1166.       $x->[$dst] = int($vd);
  1167.       $dst++;
  1168.       }
  1169.     splice (@$x,$dst) if $dst > 0;        # kill left-over array elems
  1170.     pop @$x if $x->[-1] == 0 && @$x > 1;    # kill last element if 0
  1171.     } # else rem == 0
  1172.   $x;
  1173.   }
  1174.  
  1175. sub _lsft
  1176.   {
  1177.   my ($c,$x,$y,$n) = @_;
  1178.  
  1179.   if ($n != 10)
  1180.     {
  1181.     $n = _new($c,$n); return _mul($c,$x, _pow($c,$n,$y));
  1182.     }
  1183.  
  1184.   # shortcut (faster) for shifting by 10) since we are in base 10eX
  1185.   # multiples of $BASE_LEN:
  1186.   my $src = scalar @$x;            # source
  1187.   my $len = _num($c,$y);        # shift-len as normal int
  1188.   my $rem = $len % $BASE_LEN;        # remainder to shift
  1189.   my $dst = $src + int($len/$BASE_LEN);    # destination
  1190.   my $vd;                # further speedup
  1191.   $x->[$src] = 0;            # avoid first ||0 for speed
  1192.   my $z = '0' x $BASE_LEN;
  1193.   while ($src >= 0)
  1194.     {
  1195.     $vd = $x->[$src]; $vd = $z.$vd;
  1196.     $vd = substr($vd,-$BASE_LEN+$rem,$BASE_LEN-$rem);
  1197.     $vd .= $src > 0 ? substr($z.$x->[$src-1],-$BASE_LEN,$rem) : '0' x $rem;
  1198.     $vd = substr($vd,-$BASE_LEN,$BASE_LEN) if length($vd) > $BASE_LEN;
  1199.     $x->[$dst] = int($vd);
  1200.     $dst--; $src--;
  1201.     }
  1202.   # set lowest parts to 0
  1203.   while ($dst >= 0) { $x->[$dst--] = 0; }
  1204.   # fix spurios last zero element
  1205.   splice @$x,-1 if $x->[-1] == 0;
  1206.   $x;
  1207.   }
  1208.  
  1209. sub _pow
  1210.   {
  1211.   # power of $x to $y
  1212.   # ref to array, ref to array, return ref to array
  1213.   my ($c,$cx,$cy) = @_;
  1214.  
  1215.   if (scalar @$cy == 1 && $cy->[0] == 0)
  1216.     {
  1217.     splice (@$cx,1); $cx->[0] = 1;        # y == 0 => x => 1
  1218.     return $cx;
  1219.     }
  1220.   if ((scalar @$cx == 1 && $cx->[0] == 1) ||    #    x == 1
  1221.       (scalar @$cy == 1 && $cy->[0] == 1))    # or y == 1
  1222.     {
  1223.     return $cx;
  1224.     }
  1225.   if (scalar @$cx == 1 && $cx->[0] == 0)
  1226.     {
  1227.     splice (@$cx,1); $cx->[0] = 0;        # 0 ** y => 0 (if not y <= 0)
  1228.     return $cx;
  1229.     }
  1230.  
  1231.   my $pow2 = _one();
  1232.  
  1233.   my $y_bin = _as_bin($c,$cy); $y_bin =~ s/^0b//;
  1234.   my $len = length($y_bin);
  1235.   while (--$len > 0)
  1236.     {
  1237.     _mul($c,$pow2,$cx) if substr($y_bin,$len,1) eq '1';        # is odd?
  1238.     _mul($c,$cx,$cx);
  1239.     }
  1240.  
  1241.   _mul($c,$cx,$pow2);
  1242.   $cx;
  1243.   }
  1244.  
  1245. sub _fac
  1246.   {
  1247.   # factorial of $x
  1248.   # ref to array, return ref to array
  1249.   my ($c,$cx) = @_;
  1250.  
  1251.   if ((@$cx == 1) && ($cx->[0] <= 2))
  1252.     {
  1253.     $cx->[0] ||= 1;        # 0 => 1, 1 => 1, 2 => 2
  1254.     return $cx;
  1255.     }
  1256.  
  1257.   # go forward until $base is exceeded
  1258.   # limit is either $x steps (steps == 100 means a result always too high) or
  1259.   # $base.
  1260.   my $steps = 100; $steps = $cx->[0] if @$cx == 1;
  1261.   my $r = 2; my $cf = 3; my $step = 2; my $last = $r;
  1262.   while ($r*$cf < $BASE && $step < $steps)
  1263.     {
  1264.     $last = $r; $r *= $cf++; $step++;
  1265.     }
  1266.   if ((@$cx == 1) && $step == $cx->[0])
  1267.     {
  1268.     # completely done, so keep reference to $x and return
  1269.     $cx->[0] = $r;
  1270.     return $cx;
  1271.     }
  1272.   
  1273.   # now we must do the left over steps
  1274.   my $n;                    # steps still to do
  1275.   if (scalar @$cx == 1)
  1276.     {
  1277.     $n = $cx->[0];
  1278.     }
  1279.   else
  1280.     {
  1281.     $n = _copy($c,$cx);
  1282.     }
  1283.  
  1284.   $cx->[0] = $last; splice (@$cx,1);        # keep ref to $x
  1285.   my $zero_elements = 0;
  1286.  
  1287.   # do left-over steps fit into a scalar?
  1288.   if (ref $n eq 'ARRAY')
  1289.     {
  1290.     # No, so use slower inc() & cmp()
  1291.     $step = [$step];
  1292.     while (_acmp($step,$n) <= 0)
  1293.       {
  1294.       # as soon as the last element of $cx is 0, we split it up and remember
  1295.       # how many zeors we got so far. The reason is that n! will accumulate
  1296.       # zeros at the end rather fast.
  1297.       if ($cx->[0] == 0)
  1298.         {
  1299.         $zero_elements ++; shift @$cx;
  1300.         }
  1301.       _mul($c,$cx,$step); _inc($c,$step);
  1302.       }
  1303.     }
  1304.   else
  1305.     {
  1306.     # Yes, so we can speed it up slightly
  1307.     while ($step <= $n)
  1308.       {
  1309.       # When the last element of $cx is 0, we split it up and remember
  1310.       # how many we got so far. The reason is that n! will accumulate
  1311.       # zeros at the end rather fast.
  1312.       if ($cx->[0] == 0)
  1313.         {
  1314.         $zero_elements ++; shift @$cx;
  1315.         }
  1316.       _mul($c,$cx,[$step]); $step++;
  1317.       }
  1318.     }
  1319.   # multiply in the zeros again
  1320.   while ($zero_elements-- > 0)
  1321.     {
  1322.     unshift @$cx, 0; 
  1323.     }
  1324.   $cx;            # return result
  1325.   }
  1326.  
  1327. #############################################################################
  1328.  
  1329. sub _log_int
  1330.   {
  1331.   # calculate integer log of $x to base $base
  1332.   # ref to array, ref to array - return ref to array
  1333.   my ($c,$x,$base) = @_;
  1334.  
  1335.   # X == 0 => NaN
  1336.   return if (scalar @$x == 1 && $x->[0] == 0);
  1337.   # BASE 0 or 1 => NaN
  1338.   return if (scalar @$base == 1 && $base->[0] < 2);
  1339.   my $cmp = _acmp($c,$x,$base); # X == BASE => 1
  1340.   if ($cmp == 0)
  1341.     {
  1342.     splice (@$x,1); $x->[0] = 1;
  1343.     return ($x,1)
  1344.     }
  1345.   # X < BASE
  1346.   if ($cmp < 0)
  1347.     {
  1348.     splice (@$x,1); $x->[0] = 0;
  1349.     return ($x,undef);
  1350.     }
  1351.  
  1352.   # this trial multiplication is very fast, even for large counts (like for
  1353.   # 2 ** 1024, since this still requires only 1024 very fast steps
  1354.   # (multiplication of a large number by a very small number is very fast))
  1355.   my $x_org = _copy($c,$x);        # preserve x
  1356.   splice(@$x,1); $x->[0] = 1;        # keep ref to $x
  1357.  
  1358.   my $trial = _copy($c,$base);
  1359.  
  1360.   # XXX TODO this only works if $base has only one element
  1361.   if (scalar @$base == 1)
  1362.     {
  1363.     # compute int ( length_in_base_10(X) / ( log(base) / log(10) ) )
  1364.     my $len = _len($c,$x_org);
  1365.     my $res = int($len / (log($base->[0]) / log(10))) || 1; # avoid $res == 0
  1366.  
  1367.     $x->[0] = $res;
  1368.     $trial = _pow ($c, _copy($c, $base), $x);
  1369.     my $a = _acmp($x,$trial,$x_org);
  1370.     return ($x,1) if $a == 0;
  1371.     # we now know that $res is too small
  1372.     if ($res < 0)
  1373.       {
  1374.       _mul($c,$trial,$base); _add($c, $x, [1]);
  1375.       }
  1376.     else
  1377.       {
  1378.       # or too big
  1379.       _div($c,$trial,$base); _sub($c, $x, [1]);
  1380.       }
  1381.     # did we now get the right result?
  1382.     $a = _acmp($x,$trial,$x_org);
  1383.     return ($x,1) if $a == 0;        # yes, exactly
  1384.     # still too big
  1385.     if ($a > 0)
  1386.       {
  1387.       _div($c,$trial,$base); _sub($c, $x, [1]);
  1388.       }
  1389.     } 
  1390.   
  1391.   # simple loop that increments $x by two in each step, possible overstepping
  1392.   # the real result by one
  1393.  
  1394.   my $a;
  1395.   my $base_mul = _mul($c, _copy($c,$base), $base);
  1396.  
  1397.   while (($a = _acmp($c,$trial,$x_org)) < 0)
  1398.     {
  1399.     _mul($c,$trial,$base_mul); _add($c, $x, [2]);
  1400.     }
  1401.  
  1402.   my $exact = 1;
  1403.   if ($a > 0)
  1404.     {
  1405.     # overstepped the result
  1406.     _dec($c, $x);
  1407.     _div($c,$trial,$base);
  1408.     $a = _acmp($c,$trial,$x_org);
  1409.     if ($a > 0)
  1410.       {
  1411.       _dec($c, $x);
  1412.       }
  1413.     $exact = 0 if $a != 0;
  1414.     }
  1415.   
  1416.   ($x,$exact);                # return result
  1417.   }
  1418.  
  1419. # for debugging:
  1420.   use constant DEBUG => 0;
  1421.   my $steps = 0;
  1422.   sub steps { $steps };
  1423.  
  1424. sub _sqrt
  1425.   {
  1426.   # square-root of $x in place
  1427.   # Compute a guess of the result (by rule of thumb), then improve it via
  1428.   # Newton's method.
  1429.   my ($c,$x) = @_;
  1430.  
  1431.   if (scalar @$x == 1)
  1432.     {
  1433.     # fit's into one Perl scalar, so result can be computed directly
  1434.     $x->[0] = int(sqrt($x->[0]));
  1435.     return $x;
  1436.     } 
  1437.   my $y = _copy($c,$x);
  1438.   # hopefully _len/2 is < $BASE, the -1 is to always undershot the guess
  1439.   # since our guess will "grow"
  1440.   my $l = int((_len($c,$x)-1) / 2);    
  1441.  
  1442.   my $lastelem = $x->[-1];                    # for guess
  1443.   my $elems = scalar @$x - 1;
  1444.   # not enough digits, but could have more?
  1445.   if ((length($lastelem) <= 3) && ($elems > 1))
  1446.     {
  1447.     # right-align with zero pad
  1448.     my $len = length($lastelem) & 1;
  1449.     print "$lastelem => " if DEBUG;
  1450.     $lastelem .= substr($x->[-2] . '0' x $BASE_LEN,0,$BASE_LEN);
  1451.     # former odd => make odd again, or former even to even again
  1452.     $lastelem = $lastelem / 10 if (length($lastelem) & 1) != $len;
  1453.     print "$lastelem\n" if DEBUG;
  1454.     }
  1455.  
  1456.   # construct $x (instead of _lsft($c,$x,$l,10)
  1457.   my $r = $l % $BASE_LEN;    # 10000 00000 00000 00000 ($BASE_LEN=5)
  1458.   $l = int($l / $BASE_LEN);
  1459.   print "l =  $l " if DEBUG;
  1460.  
  1461.   splice @$x,$l;        # keep ref($x), but modify it
  1462.  
  1463.   # we make the first part of the guess not '1000...0' but int(sqrt($lastelem))
  1464.   # that gives us:
  1465.   # 14400 00000 => sqrt(14400) => guess first digits to be 120
  1466.   # 144000 000000 => sqrt(144000) => guess 379
  1467.  
  1468.   print "$lastelem (elems $elems) => " if DEBUG;
  1469.   $lastelem = $lastelem / 10 if ($elems & 1 == 1);        # odd or even?
  1470.   my $g = sqrt($lastelem); $g =~ s/\.//;            # 2.345 => 2345
  1471.   $r -= 1 if $elems & 1 == 0;                    # 70 => 7
  1472.  
  1473.   # padd with zeros if result is too short
  1474.   $x->[$l--] = int(substr($g . '0' x $r,0,$r+1));
  1475.   print "now ",$x->[-1] if DEBUG;
  1476.   print " would have been ", int('1' . '0' x $r),"\n" if DEBUG;
  1477.  
  1478.   # If @$x > 1, we could compute the second elem of the guess, too, to create
  1479.   # an even better guess. Not implemented yet. Does it improve performance?
  1480.   $x->[$l--] = 0 while ($l >= 0);    # all other digits of guess are zero
  1481.  
  1482.   print "start x= ",_str($c,$x),"\n" if DEBUG;
  1483.   my $two = _two();
  1484.   my $last = _zero();
  1485.   my $lastlast = _zero();
  1486.   $steps = 0 if DEBUG;
  1487.   while (_acmp($c,$last,$x) != 0 && _acmp($c,$lastlast,$x) != 0)
  1488.     {
  1489.     $steps++ if DEBUG;
  1490.     $lastlast = _copy($c,$last);
  1491.     $last = _copy($c,$x);
  1492.     _add($c,$x, _div($c,_copy($c,$y),$x));
  1493.     _div($c,$x, $two );
  1494.     print " x= ",_str($c,$x),"\n" if DEBUG;
  1495.     }
  1496.   print "\nsteps in sqrt: $steps, " if DEBUG;
  1497.   _dec($c,$x) if _acmp($c,$y,_mul($c,_copy($c,$x),$x)) < 0;    # overshot? 
  1498.   print " final ",$x->[-1],"\n" if DEBUG;
  1499.   $x;
  1500.   }
  1501.  
  1502. sub _root
  1503.   {
  1504.   # take n'th root of $x in place (n >= 3)
  1505.   my ($c,$x,$n) = @_;
  1506.  
  1507.   if (scalar @$x == 1)
  1508.     {
  1509.     if (scalar @$n > 1)
  1510.       {
  1511.       # result will always be smaller than 2 so trunc to 1 at once
  1512.       $x->[0] = 1;
  1513.       }
  1514.     else
  1515.       {
  1516.       # fit's into one Perl scalar, so result can be computed directly
  1517.       # cannot use int() here, because it rounds wrongly (try 
  1518.       # (81 ** 3) ** (1/3) to see what I mean)
  1519.       #$x->[0] = int( $x->[0] ** (1 / $n->[0]) );
  1520.       # round to 8 digits, then truncate result to integer
  1521.       $x->[0] = int ( sprintf ("%.8f", $x->[0] ** (1 / $n->[0]) ) );
  1522.       }
  1523.     return $x;
  1524.     } 
  1525.  
  1526.   # we know now that X is more than one element long
  1527.  
  1528.   # if $n is a power of two, we can repeatedly take sqrt($X) and find the
  1529.   # proper result, because sqrt(sqrt($x)) == root($x,4)
  1530.   my $b = _as_bin($c,$n);
  1531.   if ($b =~ /0b1(0+)$/)
  1532.     {
  1533.     my $count = CORE::length($1);    # 0b100 => len('00') => 2
  1534.     my $cnt = $count;            # counter for loop
  1535.     unshift (@$x, 0);            # add one element, together with one
  1536.                     # more below in the loop this makes 2
  1537.     while ($cnt-- > 0)
  1538.       {
  1539.       # 'inflate' $X by adding one element, basically computing
  1540.       # $x * $BASE * $BASE. This gives us more $BASE_LEN digits for result
  1541.       # since len(sqrt($X)) approx == len($x) / 2.
  1542.       unshift (@$x, 0);
  1543.       # calculate sqrt($x), $x is now one element to big, again. In the next
  1544.       # round we make that two, again.
  1545.       _sqrt($c,$x);
  1546.       }
  1547.     # $x is now one element to big, so truncate result by removing it
  1548.     splice (@$x,0,1);
  1549.     } 
  1550.   else
  1551.     {
  1552.     # trial computation by starting with 2,4,8,16 etc until we overstep
  1553.     my $step;
  1554.     my $trial = _two();
  1555.  
  1556.     # while still to do more than X steps
  1557.     do
  1558.       {
  1559.       $step = _two();
  1560.       while (_acmp($c, _pow($c, _copy($c, $trial), $n), $x) < 0)
  1561.         {
  1562.         _mul ($c, $step, [2]);
  1563.         _add ($c, $trial, $step);
  1564.         }
  1565.  
  1566.       # hit exactly?
  1567.       if (_acmp($c, _pow($c, _copy($c, $trial), $n), $x) == 0)
  1568.         {
  1569.         @$x = @$trial;            # make copy while preserving ref to $x
  1570.         return $x;
  1571.         }
  1572.       # overstepped, so go back on step
  1573.       _sub($c, $trial, $step);
  1574.       } while (scalar @$step > 1 || $step->[0] > 128);
  1575.  
  1576.     # reset step to 2
  1577.     $step = _two();
  1578.     # add two, because $trial cannot be exactly the result (otherwise we would
  1579.     # alrady have found it)
  1580.     _add($c, $trial, $step);
  1581.  
  1582.     # and now add more and more (2,4,6,8,10 etc)
  1583.     while (_acmp($c, _pow($c, _copy($c, $trial), $n), $x) < 0)
  1584.       {
  1585.       _add ($c, $trial, $step);
  1586.       }
  1587.  
  1588.     # hit not exactly? (overstepped)
  1589.     if (_acmp($c, _pow($c, _copy($c, $trial), $n), $x) > 0)
  1590.       {
  1591.       _dec($c,$trial);
  1592.       }
  1593.  
  1594.     # hit not exactly? (overstepped)
  1595.     # 80 too small, 81 slightly too big, 82 too big
  1596.     if (_acmp($c, _pow($c, _copy($c, $trial), $n), $x) > 0)
  1597.       {
  1598.       _dec ($c, $trial); 
  1599.       }
  1600.  
  1601.     @$x = @$trial;            # make copy while preserving ref to $x
  1602.     return $x;
  1603.     }
  1604.   $x; 
  1605.   }
  1606.  
  1607. ##############################################################################
  1608. # binary stuff
  1609.  
  1610. sub _and
  1611.   {
  1612.   my ($c,$x,$y) = @_;
  1613.  
  1614.   # the shortcut makes equal, large numbers _really_ fast, and makes only a
  1615.   # very small performance drop for small numbers (e.g. something with less
  1616.   # than 32 bit) Since we optimize for large numbers, this is enabled.
  1617.   return $x if _acmp($c,$x,$y) == 0;        # shortcut
  1618.   
  1619.   my $m = _one(); my ($xr,$yr);
  1620.   my $mask = $AND_MASK;
  1621.  
  1622.   my $x1 = $x;
  1623.   my $y1 = _copy($c,$y);            # make copy
  1624.   $x = _zero();
  1625.   my ($b,$xrr,$yrr);
  1626.   use integer;
  1627.   while (!_is_zero($c,$x1) && !_is_zero($c,$y1))
  1628.     {
  1629.     ($x1, $xr) = _div($c,$x1,$mask);
  1630.     ($y1, $yr) = _div($c,$y1,$mask);
  1631.  
  1632.     # make ints() from $xr, $yr
  1633.     # this is when the AND_BITS are greater than $BASE and is slower for
  1634.     # small (<256 bits) numbers, but faster for large numbers. Disabled
  1635.     # due to KISS principle
  1636.  
  1637. #    $b = 1; $xrr = 0; foreach (@$xr) { $xrr += $_ * $b; $b *= $BASE; }
  1638. #    $b = 1; $yrr = 0; foreach (@$yr) { $yrr += $_ * $b; $b *= $BASE; }
  1639. #    _add($c,$x, _mul($c, _new( $c, ($xrr & $yrr) ), $m) );
  1640.     
  1641.     # 0+ due to '&' doesn't work in strings
  1642.     _add($c,$x, _mul($c, [ 0+$xr->[0] & 0+$yr->[0] ], $m) );
  1643.     _mul($c,$m,$mask);
  1644.     }
  1645.   $x;
  1646.   }
  1647.  
  1648. sub _xor
  1649.   {
  1650.   my ($c,$x,$y) = @_;
  1651.  
  1652.   return _zero() if _acmp($c,$x,$y) == 0;    # shortcut (see -and)
  1653.  
  1654.   my $m = _one(); my ($xr,$yr);
  1655.   my $mask = $XOR_MASK;
  1656.  
  1657.   my $x1 = $x;
  1658.   my $y1 = _copy($c,$y);            # make copy
  1659.   $x = _zero();
  1660.   my ($b,$xrr,$yrr);
  1661.   use integer;
  1662.   while (!_is_zero($c,$x1) && !_is_zero($c,$y1))
  1663.     {
  1664.     ($x1, $xr) = _div($c,$x1,$mask);
  1665.     ($y1, $yr) = _div($c,$y1,$mask);
  1666.     # make ints() from $xr, $yr (see _and())
  1667.     #$b = 1; $xrr = 0; foreach (@$xr) { $xrr += $_ * $b; $b *= $BASE; }
  1668.     #$b = 1; $yrr = 0; foreach (@$yr) { $yrr += $_ * $b; $b *= $BASE; }
  1669.     #_add($c,$x, _mul($c, _new( $c, ($xrr ^ $yrr) ), $m) );
  1670.  
  1671.     # 0+ due to '^' doesn't work in strings
  1672.     _add($c,$x, _mul($c, [ 0+$xr->[0] ^ 0+$yr->[0] ], $m) );
  1673.     _mul($c,$m,$mask);
  1674.     }
  1675.   # the loop stops when the shorter of the two numbers is exhausted
  1676.   # the remainder of the longer one will survive bit-by-bit, so we simple
  1677.   # multiply-add it in
  1678.   _add($c,$x, _mul($c, $x1, $m) ) if !_is_zero($c,$x1);
  1679.   _add($c,$x, _mul($c, $y1, $m) ) if !_is_zero($c,$y1);
  1680.   
  1681.   $x;
  1682.   }
  1683.  
  1684. sub _or
  1685.   {
  1686.   my ($c,$x,$y) = @_;
  1687.  
  1688.   return $x if _acmp($c,$x,$y) == 0;        # shortcut (see _and)
  1689.  
  1690.   my $m = _one(); my ($xr,$yr);
  1691.   my $mask = $OR_MASK;
  1692.  
  1693.   my $x1 = $x;
  1694.   my $y1 = _copy($c,$y);            # make copy
  1695.   $x = _zero();
  1696.   my ($b,$xrr,$yrr);
  1697.   use integer;
  1698.   while (!_is_zero($c,$x1) && !_is_zero($c,$y1))
  1699.     {
  1700.     ($x1, $xr) = _div($c,$x1,$mask);
  1701.     ($y1, $yr) = _div($c,$y1,$mask);
  1702.     # make ints() from $xr, $yr (see _and())
  1703. #    $b = 1; $xrr = 0; foreach (@$xr) { $xrr += $_ * $b; $b *= $BASE; }
  1704. #    $b = 1; $yrr = 0; foreach (@$yr) { $yrr += $_ * $b; $b *= $BASE; }
  1705. #    _add($c,$x, _mul($c, _new( $c, ($xrr | $yrr) ), $m) );
  1706.     
  1707.     # 0+ due to '|' doesn't work in strings
  1708.     _add($c,$x, _mul($c, [ 0+$xr->[0] | 0+$yr->[0] ], $m) );
  1709.     _mul($c,$m,$mask);
  1710.     }
  1711.   # the loop stops when the shorter of the two numbers is exhausted
  1712.   # the remainder of the longer one will survive bit-by-bit, so we simple
  1713.   # multiply-add it in
  1714.   _add($c,$x, _mul($c, $x1, $m) ) if !_is_zero($c,$x1);
  1715.   _add($c,$x, _mul($c, $y1, $m) ) if !_is_zero($c,$y1);
  1716.   
  1717.   $x;
  1718.   }
  1719.  
  1720. sub _as_hex
  1721.   {
  1722.   # convert a decimal number to hex (ref to array, return ref to string)
  1723.   my ($c,$x) = @_;
  1724.  
  1725.   # fit's into one element (handle also 0x0 case)
  1726.   return sprintf("0x%x",$x->[0]) if @$x == 1;
  1727.  
  1728.   my $x1 = _copy($c,$x);
  1729.  
  1730.   my $es = '';
  1731.   my ($xr, $h, $x10000);
  1732.   if ($] >= 5.006)
  1733.     {
  1734.     $x10000 = [ 0x10000 ]; $h = 'h4';
  1735.     }
  1736.   else
  1737.     {
  1738.     $x10000 = [ 0x1000 ]; $h = 'h3';
  1739.     }
  1740.   while (@$x1 != 1 || $x1->[0] != 0)        # _is_zero()
  1741.     {
  1742.     ($x1, $xr) = _div($c,$x1,$x10000);
  1743.     $es .= unpack($h,pack('v',$xr->[0]));    # XXX TODO: why pack('v',...)?
  1744.     }
  1745.   $es = reverse $es;
  1746.   $es =~ s/^[0]+//;   # strip leading zeros
  1747.   '0x' . $es;                    # return result prepended with 0x
  1748.   }
  1749.  
  1750. sub _as_bin
  1751.   {
  1752.   # convert a decimal number to bin (ref to array, return ref to string)
  1753.   my ($c,$x) = @_;
  1754.  
  1755.   # fit's into one element (and Perl recent enough), handle also 0b0 case
  1756.   # handle zero case for older Perls
  1757.   if ($] <= 5.005 && @$x == 1 && $x->[0] == 0)
  1758.     {
  1759.     my $t = '0b0'; return $t;
  1760.     }
  1761.   if (@$x == 1 && $] >= 5.006)
  1762.     {
  1763.     my $t = sprintf("0b%b",$x->[0]);
  1764.     return $t;
  1765.     }
  1766.   my $x1 = _copy($c,$x);
  1767.  
  1768.   my $es = '';
  1769.   my ($xr, $b, $x10000);
  1770.   if ($] >= 5.006)
  1771.     {
  1772.     $x10000 = [ 0x10000 ]; $b = 'b16';
  1773.     }
  1774.   else
  1775.     {
  1776.     $x10000 = [ 0x1000 ]; $b = 'b12';
  1777.     }
  1778.   while (!(@$x1 == 1 && $x1->[0] == 0))        # _is_zero()
  1779.     {
  1780.     ($x1, $xr) = _div($c,$x1,$x10000);
  1781.     $es .= unpack($b,pack('v',$xr->[0]));    # XXX TODO: why pack('v',...)?
  1782.     # $es .= unpack($b,$xr->[0]);
  1783.     }
  1784.   $es = reverse $es;
  1785.   $es =~ s/^[0]+//;   # strip leading zeros
  1786.   '0b' . $es;                    # return result prepended with 0b
  1787.   }
  1788.  
  1789. sub _from_hex
  1790.   {
  1791.   # convert a hex number to decimal (ref to string, return ref to array)
  1792.   my ($c,$hs) = @_;
  1793.  
  1794.   my $m = _new($c, 0x10000000);            # 28 bit at a time (<32 bit!)
  1795.   my $d = 7;                    # 7 digits at a time
  1796.   if ($] <= 5.006)
  1797.     {
  1798.     # for older Perls, play safe
  1799.     $m = [ 0x10000 ];                # 16 bit at a time (<32 bit!)
  1800.     $d = 4;                    # 4 digits at a time
  1801.     }
  1802.  
  1803.   my $mul = _one();
  1804.   my $x = _zero();
  1805.  
  1806.   my $len = int( (length($hs)-2)/$d );        # $d digit parts, w/o the '0x'
  1807.   my $val; my $i = -$d;
  1808.   while ($len >= 0)
  1809.     {
  1810.     $val = substr($hs,$i,$d);            # get hex digits
  1811.     $val =~ s/^[+-]?0x// if $len == 0;        # for last part only because
  1812.     $val = hex($val);                # hex does not like wrong chars
  1813.     $i -= $d; $len --;
  1814.     my $adder = [ $val ];
  1815.     # if the resulting number was to big to fit into one element, create a
  1816.     # two-element version (bug found by Mark Lakata - Thanx!)
  1817.     if (CORE::length($val) > $BASE_LEN)
  1818.       {
  1819.       $adder = _new($c,$val);
  1820.       }
  1821.     _add ($c, $x, _mul ($c, $adder, $mul ) ) if $val != 0;
  1822.     _mul ($c, $mul, $m ) if $len >= 0;         # skip last mul
  1823.     }
  1824.   $x;
  1825.   }
  1826.  
  1827. sub _from_bin
  1828.   {
  1829.   # convert a hex number to decimal (ref to string, return ref to array)
  1830.   my ($c,$bs) = @_;
  1831.  
  1832.   # instead of converting X (8) bit at a time, it is faster to "convert" the
  1833.   # number to hex, and then call _from_hex.
  1834.  
  1835.   my $hs = $bs;
  1836.   $hs =~ s/^[+-]?0b//;                    # remove sign and 0b
  1837.   my $l = length($hs);                    # bits
  1838.   $hs = '0' x (8-($l % 8)) . $hs if ($l % 8) != 0;    # padd left side w/ 0
  1839.   my $h = '0x' . unpack('H*', pack ('B*', $hs));    # repack as hex
  1840.   
  1841.   $c->_from_hex($h);
  1842.   }
  1843.  
  1844. ##############################################################################
  1845. # special modulus functions
  1846.  
  1847. sub _modinv
  1848.   {
  1849.   # modular inverse
  1850.   my ($c,$x,$y) = @_;
  1851.  
  1852.   my $u = _zero($c); my $u1 = _one($c);
  1853.   my $a = _copy($c,$y); my $b = _copy($c,$x);
  1854.  
  1855.   # Euclid's Algorithm for bgcd(), only that we calc bgcd() ($a) and the
  1856.   # result ($u) at the same time. See comments in BigInt for why this works.
  1857.   my $q;
  1858.   ($a, $q, $b) = ($b, _div($c,$a,$b));        # step 1
  1859.   my $sign = 1;
  1860.   while (!_is_zero($c,$b))
  1861.     {
  1862.     my $t = _add($c,                 # step 2:
  1863.        _mul($c,_copy($c,$u1), $q) ,        #  t =  u1 * q
  1864.        $u );                    #     + u
  1865.     $u = $u1;                    #  u = u1, u1 = t
  1866.     $u1 = $t;
  1867.     $sign = -$sign;
  1868.     ($a, $q, $b) = ($b, _div($c,$a,$b));    # step 1
  1869.     }
  1870.  
  1871.   # if the gcd is not 1, then return NaN
  1872.   return (undef,undef) unless _is_one($c,$a);
  1873.  
  1874.   ($u1, $sign == 1 ? '+' : '-');
  1875.   }
  1876.  
  1877. sub _modpow
  1878.   {
  1879.   # modulus of power ($x ** $y) % $z
  1880.   my ($c,$num,$exp,$mod) = @_;
  1881.  
  1882.   # in the trivial case,
  1883.   if (_is_one($c,$mod))
  1884.     {
  1885.     splice @$num,0,1; $num->[0] = 0;
  1886.     return $num;
  1887.     }
  1888.   if ((scalar @$num == 1) && (($num->[0] == 0) || ($num->[0] == 1)))
  1889.     {
  1890.     $num->[0] = 1;
  1891.     return $num;
  1892.     }
  1893.  
  1894. #  $num = _mod($c,$num,$mod);    # this does not make it faster
  1895.  
  1896.   my $acc = _copy($c,$num); my $t = _one();
  1897.  
  1898.   my $expbin = _as_bin($c,$exp); $expbin =~ s/^0b//;
  1899.   my $len = length($expbin);
  1900.   while (--$len >= 0)
  1901.     {
  1902.     if ( substr($expbin,$len,1) eq '1')            # is_odd
  1903.       {
  1904.       _mul($c,$t,$acc);
  1905.       $t = _mod($c,$t,$mod);
  1906.       }
  1907.     _mul($c,$acc,$acc);
  1908.     $acc = _mod($c,$acc,$mod);
  1909.     }
  1910.   @$num = @$t;
  1911.   $num;
  1912.   }
  1913.  
  1914. sub _gcd
  1915.   {
  1916.   # greatest common divisor
  1917.   my ($c,$x,$y) = @_;
  1918.  
  1919.   while ( (scalar @$y != 1) || ($y->[0] != 0) )        # while ($y != 0)
  1920.     {
  1921.     my $t = _copy($c,$y);
  1922.     $y = _mod($c, $x, $y);
  1923.     $x = $t;
  1924.     }
  1925.   $x;
  1926.   }
  1927.  
  1928. ##############################################################################
  1929. ##############################################################################
  1930.  
  1931. 1;
  1932. __END__
  1933.  
  1934. =head1 NAME
  1935.  
  1936. Math::BigInt::Calc - Pure Perl module to support Math::BigInt
  1937.  
  1938. =head1 SYNOPSIS
  1939.  
  1940. Provides support for big integer calculations. Not intended to be used by other
  1941. modules. Other modules which sport the same functions can also be used to support
  1942. Math::BigInt, like Math::BigInt::GMP or Math::BigInt::Pari.
  1943.  
  1944. =head1 DESCRIPTION
  1945.  
  1946. In order to allow for multiple big integer libraries, Math::BigInt was
  1947. rewritten to use library modules for core math routines. Any module which
  1948. follows the same API as this can be used instead by using the following:
  1949.  
  1950.     use Math::BigInt lib => 'libname';
  1951.  
  1952. 'libname' is either the long name ('Math::BigInt::Pari'), or only the short
  1953. version like 'Pari'.
  1954.  
  1955. =head1 STORAGE
  1956.  
  1957. =head1 METHODS
  1958.  
  1959. The following functions MUST be defined in order to support the use by
  1960. Math::BigInt v1.70 or later:
  1961.  
  1962.     api_version()    return API version, minimum 1 for v1.70
  1963.     _new(string)    return ref to new object from ref to decimal string
  1964.     _zero()        return a new object with value 0
  1965.     _one()        return a new object with value 1
  1966.     _two()        return a new object with value 2
  1967.     _ten()        return a new object with value 10
  1968.  
  1969.     _str(obj)    return ref to a string representing the object
  1970.     _num(obj)    returns a Perl integer/floating point number
  1971.             NOTE: because of Perl numeric notation defaults,
  1972.             the _num'ified obj may lose accuracy due to 
  1973.             machine-dependend floating point size limitations
  1974.                     
  1975.     _add(obj,obj)    Simple addition of two objects
  1976.     _mul(obj,obj)    Multiplication of two objects
  1977.     _div(obj,obj)    Division of the 1st object by the 2nd
  1978.             In list context, returns (result,remainder).
  1979.             NOTE: this is integer math, so no
  1980.             fractional part will be returned.
  1981.             The second operand will be not be 0, so no need to
  1982.             check for that.
  1983.     _sub(obj,obj)    Simple subtraction of 1 object from another
  1984.             a third, optional parameter indicates that the params
  1985.             are swapped. In this case, the first param needs to
  1986.             be preserved, while you can destroy the second.
  1987.             sub (x,y,1) => return x - y and keep x intact!
  1988.     _dec(obj)    decrement object by one (input is garant. to be > 0)
  1989.     _inc(obj)    increment object by one
  1990.  
  1991.  
  1992.     _acmp(obj,obj)    <=> operator for objects (return -1, 0 or 1)
  1993.  
  1994.     _len(obj)    returns count of the decimal digits of the object
  1995.     _digit(obj,n)    returns the n'th decimal digit of object
  1996.  
  1997.     _is_one(obj)    return true if argument is 1
  1998.     _is_two(obj)    return true if argument is 2
  1999.     _is_ten(obj)    return true if argument is 10
  2000.     _is_zero(obj)    return true if argument is 0
  2001.     _is_even(obj)    return true if argument is even (0,2,4,6..)
  2002.     _is_odd(obj)    return true if argument is odd (1,3,5,7..)
  2003.  
  2004.     _copy        return a ref to a true copy of the object
  2005.  
  2006.     _check(obj)    check whether internal representation is still intact
  2007.             return 0 for ok, otherwise error message as string
  2008.  
  2009.     _from_hex(str)    return ref to new object from ref to hexadecimal string
  2010.     _from_bin(str)    return ref to new object from ref to binary string
  2011.     
  2012.     _as_hex(str)    return string containing the value as
  2013.             unsigned hex string, with the '0x' prepended.
  2014.             Leading zeros must be stripped.
  2015.     _as_bin(str)    Like as_hex, only as binary string containing only
  2016.             zeros and ones. Leading zeros must be stripped and a
  2017.             '0b' must be prepended.
  2018.     
  2019.     _rsft(obj,N,B)    shift object in base B by N 'digits' right
  2020.     _lsft(obj,N,B)    shift object in base B by N 'digits' left
  2021.     
  2022.     _xor(obj1,obj2)    XOR (bit-wise) object 1 with object 2
  2023.             Note: XOR, AND and OR pad with zeros if size mismatches
  2024.     _and(obj1,obj2)    AND (bit-wise) object 1 with object 2
  2025.     _or(obj1,obj2)    OR (bit-wise) object 1 with object 2
  2026.  
  2027.     _mod(obj,obj)    Return remainder of div of the 1st by the 2nd object
  2028.     _sqrt(obj)    return the square root of object (truncated to int)
  2029.     _root(obj)    return the n'th (n >= 3) root of obj (truncated to int)
  2030.     _fac(obj)    return factorial of object 1 (1*2*3*4..)
  2031.     _pow(obj,obj)    return object 1 to the power of object 2
  2032.             return undef for NaN
  2033.     _zeros(obj)    return number of trailing decimal zeros
  2034.     _modinv        return inverse modulus
  2035.     _modpow        return modulus of power ($x ** $y) % $z
  2036.     _log_int(X,N)    calculate integer log() of X in base N
  2037.             X >= 0, N >= 0 (return undef for NaN)
  2038.             returns (RESULT, EXACT) where EXACT is:
  2039.              1     : result is exactly RESULT
  2040.              0     : result was truncated to RESULT
  2041.              undef : unknown whether result is exactly RESULT
  2042.         _gcd(obj,obj)    return Greatest Common Divisor of two objects
  2043.  
  2044. The following functions are optional, and can be defined if the underlying lib
  2045. has a fast way to do them. If undefined, Math::BigInt will use pure Perl (hence
  2046. slow) fallback routines to emulate these:
  2047.     
  2048.     _signed_or
  2049.     _signed_and
  2050.     _signed_xor
  2051.  
  2052.  
  2053. Input strings come in as unsigned but with prefix (i.e. as '123', '0xabc'
  2054. or '0b1101').
  2055.  
  2056. So the library needs only to deal with unsigned big integers. Testing of input
  2057. parameter validity is done by the caller, so you need not worry about
  2058. underflow (f.i. in C<_sub()>, C<_dec()>) nor about division by zero or similar
  2059. cases.
  2060.  
  2061. The first parameter can be modified, that includes the possibility that you
  2062. return a reference to a completely different object instead. Although keeping
  2063. the reference and just changing it's contents is prefered over creating and
  2064. returning a different reference.
  2065.  
  2066. Return values are always references to objects, strings, or true/false for
  2067. comparisation routines.
  2068.  
  2069. =head1 WRAP YOUR OWN
  2070.  
  2071. If you want to port your own favourite c-lib for big numbers to the
  2072. Math::BigInt interface, you can take any of the already existing modules as
  2073. a rough guideline. You should really wrap up the latest BigInt and BigFloat
  2074. testsuites with your module, and replace in them any of the following:
  2075.  
  2076.     use Math::BigInt;
  2077.  
  2078. by this:
  2079.  
  2080.     use Math::BigInt lib => 'yourlib';
  2081.  
  2082. This way you ensure that your library really works 100% within Math::BigInt.
  2083.  
  2084. =head1 LICENSE
  2085.  
  2086. This program is free software; you may redistribute it and/or modify it under
  2087. the same terms as Perl itself. 
  2088.  
  2089. =head1 AUTHORS
  2090.  
  2091. Original math code by Mark Biggar, rewritten by Tels L<http://bloodgate.com/>
  2092. in late 2000.
  2093. Seperated from BigInt and shaped API with the help of John Peacock.
  2094.  
  2095. Fixed, speed-up, streamlined and enhanced by Tels 2001 - 2005.
  2096.  
  2097. =head1 SEE ALSO
  2098.  
  2099. L<Math::BigInt>, L<Math::BigFloat>, L<Math::BigInt::BitVect>,
  2100. L<Math::BigInt::GMP>, L<Math::BigInt::FastCalc> and L<Math::BigInt::Pari>.
  2101.  
  2102. =cut
  2103.